#cmake file for project erpc
#author:guyadong
#created:2020/10/19
cmake_minimum_required( VERSION 3.0 )
cmake_policy(SET CMP0048 NEW)
# 3.0以上版本才允许使用VERSION option
project(erpc VERSION 1.0.0 LANGUAGES C CXX)
#判断编译类型和版本是否满足编译要求
if(MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19)
	message(STATUS "CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") 
	message(STATUS "CMAKE_CXX_COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}" )
elseif(CMAKE_COMPILER_IS_GNUCXX)
	include(CheckCXXCompilerFlag)
	check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11)
	if(COMPILER_SUPPORTS_CXX11)
		message(STATUS "CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") 
		message(STATUS "CMAKE_CXX_COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}" )
	else()
		message(FATAL_ERROR "gnu compiler c++11 SUPPORT REQUIRED")
	endif()
else()
	message(FATAL_ERROR "compiler requirement: Visual Studio 2015 OR gnu compiler" )
endif()
# includes utils.cmake module
list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)
include (utils)
cxx11_support()
if(MSVC)
	#关闭C4819警告
	add_definitions("/wd4819")		
	message(STATUS "optional:/wd4819")
	#关闭CRT_SECURE警告
	add_definitions(-D_CRT_SECURE_NO_WARNINGS)
	message(STATUS "optional:-D_CRT_SECURE_NO_WARNINGS")
endif(MSVC)
if(CMAKE_COMPILER_IS_GNUCXX)
	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++" )
	set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++" )
	if(WIN32)
		set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc" )
		set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc" )
	endif()
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

option(CONCURRENCY_SUPPORT "server support concurrent request" ON)
option(OUTPUT_DEBUG_LOG "output tcp transport debug log" OFF)


##############设置目标文件生成位置#####################
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(RUNTIME_INSTALL_DIR bin)
set(LIBRARY_INSTALL_DIR lib)
set(INCLUDE_INSTALL_DIR include)
if(WIN32 AND NOT CYGWIN)
  set (CONFIG_INSTALL_DIR  cmake)
else()
  set (CONFIG_INSTALL_DIR  ${LIBRARY_INSTALL_DIR}/cmake/erpc)
endif()

set(_erpc_targets)
################# 创建 erpc 静态库 ###################
set(ERPC_C_LIB_NAME erpc)
set(ERPC_C_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/erpc/erpc_c)
set(ERPC_C_SOURCES  
			${ERPC_C_ROOT}/infra/erpc_arbitrated_client_manager.cpp 
			${ERPC_C_ROOT}/infra/erpc_basic_codec.cpp 
			${ERPC_C_ROOT}/infra/erpc_client_manager.cpp 
			${ERPC_C_ROOT}/infra/erpc_crc16.cpp 
			${ERPC_C_ROOT}/infra/erpc_framed_transport.cpp 
			${ERPC_C_ROOT}/infra/erpc_message_buffer.cpp 
			${ERPC_C_ROOT}/infra/erpc_message_loggers.cpp 
			${ERPC_C_ROOT}/infra/erpc_server.cpp 
			${ERPC_C_ROOT}/infra/erpc_simple_server.cpp 
			${ERPC_C_ROOT}/infra/erpc_transport_arbitrator.cpp 
			${ERPC_C_ROOT}/port/erpc_port_stdlib.cpp 
			${ERPC_C_ROOT}/port/erpc_threading_pthreads.cpp 
			${ERPC_C_ROOT}/port/erpc_serial.cpp 
			${ERPC_C_ROOT}/setup/erpc_client_setup.cpp 
			${ERPC_C_ROOT}/setup/erpc_server_setup.cpp 
			${ERPC_C_ROOT}/setup/erpc_setup_serial.cpp 
			${ERPC_C_ROOT}/setup/erpc_setup_mbf_dynamic.cpp 
			${ERPC_C_ROOT}/transports/erpc_inter_thread_buffer_transport.cpp 
			${ERPC_C_ROOT}/transports/erpc_serial_transport.cpp 
			${ERPC_C_ROOT}/transports/erpc_tcp_transport.cpp)

set(ERPC_C_HEADERS ${ERPC_C_ROOT}/config/erpc_config.h 
			${ERPC_C_ROOT}/infra/erpc_arbitrated_client_manager.h 
			${ERPC_C_ROOT}/infra/erpc_basic_codec.h 
			${ERPC_C_ROOT}/infra/erpc_client_manager.h 
			${ERPC_C_ROOT}/infra/erpc_codec.h 
			${ERPC_C_ROOT}/infra/erpc_crc16.h 
			${ERPC_C_ROOT}/infra/erpc_common.h 
			${ERPC_C_ROOT}/infra/erpc_version.h 
			${ERPC_C_ROOT}/infra/erpc_framed_transport.h 
			${ERPC_C_ROOT}/infra/erpc_manually_constructed.h 
			${ERPC_C_ROOT}/infra/erpc_message_buffer.h 
			${ERPC_C_ROOT}/infra/erpc_message_loggers.h 
			${ERPC_C_ROOT}/infra/erpc_server.h 
			${ERPC_C_ROOT}/infra/erpc_static_queue.h 
			${ERPC_C_ROOT}/infra/erpc_transport_arbitrator.h 
			${ERPC_C_ROOT}/infra/erpc_transport.h 
			${ERPC_C_ROOT}/port/erpc_config_internal.h 
			${ERPC_C_ROOT}/port/erpc_port.h 
			${ERPC_C_ROOT}/port/erpc_threading.h 
			${ERPC_C_ROOT}/port/erpc_serial.h 
			${ERPC_C_ROOT}/setup/erpc_arbitrated_client_setup.h 
			${ERPC_C_ROOT}/setup/erpc_client_setup.h 
			${ERPC_C_ROOT}/setup/erpc_server_setup.h 
			${ERPC_C_ROOT}/setup/erpc_transport_setup.h 
			${ERPC_C_ROOT}/setup/erpc_mbf_setup.h 
			${ERPC_C_ROOT}/transports/erpc_inter_thread_buffer_transport.h 
			${ERPC_C_ROOT}/transports/erpc_serial_transport.h 
			${ERPC_C_ROOT}/transports/erpc_tcp_transport.h )

if(CONCURRENCY_SUPPORT)
# 添加线程池实现代码
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/concurrency CONCURRENCY_SOURCES)
# 添加线程池实现代码
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dual DUAL_SOURCES)

list(APPEND ERPC_C_SOURCES ${CONCURRENCY_SOURCES} ${DUAL_SOURCES})
list(APPEND ERPC_C_HEADERS
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_concurrency_server.h 
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_concurrency_server_setup.h
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_server_tcp_transport.h
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_setup_server_tcp.h
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_client_tcp_transport.h
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_setup_client_tcp.h
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_setup_tcp.h
	${CMAKE_CURRENT_SOURCE_DIR}/dual/erpc_dual_serial_transport.h
	${CMAKE_CURRENT_SOURCE_DIR}/dual/erpc_setup_dual_serial.h
	 )
endif(CONCURRENCY_SUPPORT)

if(WIN32 AND NOT CYGWIN)
list(REMOVE_ITEM ERPC_C_SOURCES
	${CMAKE_CURRENT_SOURCE_DIR}/dual/erpc_dual_serial_transport.cpp
	${CMAKE_CURRENT_SOURCE_DIR}/dual/erpc_setup_dual_serial.cpp
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_setup_tcp.cpp
	${ERPC_C_ROOT}/transports/erpc_tcp_transport.cpp
	${ERPC_C_ROOT}/port/erpc_serial.cpp 
	${ERPC_C_ROOT}/setup/erpc_setup_serial.cpp 
	${ERPC_C_ROOT}/transports/erpc_serial_transport.cpp 		
	)
list(REMOVE_ITEM ERPC_C_HEADERS
	${CMAKE_CURRENT_SOURCE_DIR}/concurrency/erpc_setup_tcp.h
	${CMAKE_CURRENT_SOURCE_DIR}/dual/erpc_dual_serial_transport.h
	${CMAKE_CURRENT_SOURCE_DIR}/dual/erpc_setup_dual_serial.h
	${ERPC_C_ROOT}/transports/erpc_tcp_transport.h
	${ERPC_C_ROOT}/port/erpc_serial.h 
	${ERPC_C_ROOT}/transports/erpc_serial_transport.h 
	)
endif()

add_library(${ERPC_C_LIB_NAME} STATIC ${ERPC_C_SOURCES} ${CONCURRENCY_SOURCES})
target_compile_options(${ERPC_C_LIB_NAME} PRIVATE $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Debug>>:/Z7> 
	$<$<CXX_COMPILER_ID:MSVC>:/wd4275 /wd4251>
	$<$<CXX_COMPILER_ID:GNU>:-Wno-format-security>)
target_include_directories (${ERPC_C_LIB_NAME}
	INTERFACE "$<INSTALL_INTERFACE:include/erpc>"			
	PUBLIC "$<BUILD_INTERFACE:${ERPC_C_ROOT}/config>"
	"$<BUILD_INTERFACE:${ERPC_C_ROOT}/infra>"
	"$<BUILD_INTERFACE:${ERPC_C_ROOT}/port>"
	"$<BUILD_INTERFACE:${ERPC_C_ROOT}/setup>"
	"$<BUILD_INTERFACE:${ERPC_C_ROOT}/transports>"
	"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/concurrency>"
	"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dual>"
	)
set_target_properties (${ERPC_C_LIB_NAME}  PROPERTIES 
	PUBLIC_HEADER "${ERPC_C_HEADERS}"
	)
set_target_properties (${ERPC_C_LIB_NAME}  PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON
	POSITION_INDEPENDENT_CODE ON)
# 开启tcp调试信息输出
target_compile_definitions(${ERPC_C_LIB_NAME} PRIVATE 
	$<$<CXX_COMPILER_ID:MSVC>:_WINSOCK_DEPRECATED_NO_WARNINGS>
	$<$<BOOL:${OUTPUT_DEBUG_LOG}>:TCP_TRANSPORT_DEBUG_LOG SERIAL_TRANSPORT_DEBUG_LOG>
	)

if(WIN32)
	if(MSVC)
		list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/pthreads-w32-2-9-1-release)
		find_package(PTHREADW32 REQUIRED)
		# 添加依赖库pthreadw32
		target_link_libraries(${ERPC_C_LIB_NAME} PUBLIC pthreadw32)
		target_compile_definitions(${ERPC_C_LIB_NAME} PUBLIC ERPC_HAS_POSIX)
	elseif(CMAKE_COMPILER_IS_GNUCXX)
		target_compile_definitions(${ERPC_C_LIB_NAME} PUBLIC ERPC_HAS_POSIX)
	else()
	 	message(FATAL_ERROR  "UNSUPPORTED compiler,MSVC or MinGW required")
	endif()	
else()
	find_package(Threads REQUIRED)
	# 添加依赖库pthread
	target_link_libraries(${ERPC_C_LIB_NAME} PUBLIC Threads::Threads)
endif(WIN32)

list(APPEND _erpc_targets ${ERPC_C_LIB_NAME})

########### 添加测试代码 ##############
add_subdirectory( test )
#####################################
include (CMakePackageConfigHelpers)

configure_package_config_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/${ERPC_C_LIB_NAME}-config.cmake
  INSTALL_DESTINATION ${CONFIG_INSTALL_DIR}
  NO_CHECK_REQUIRED_COMPONENTS_MACRO)
write_basic_package_version_file (${ERPC_C_LIB_NAME}-config-version.cmake VERSION
  ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion)
################安装脚本#################
install(TARGETS ${_erpc_targets} EXPORT ${ERPC_C_LIB_NAME}-targets
  RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
  LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR}
  ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR}
  PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/${ERPC_C_LIB_NAME}
  )
install (FILES
  ${CMAKE_CURRENT_BINARY_DIR}/${ERPC_C_LIB_NAME}-config.cmake
  ${CMAKE_CURRENT_BINARY_DIR}/${ERPC_C_LIB_NAME}-config-version.cmake
  DESTINATION ${CONFIG_INSTALL_DIR}
  )

install (EXPORT ${ERPC_C_LIB_NAME}-targets DESTINATION ${CONFIG_INSTALL_DIR} )
